#!/usr/bin/perl
use warnings;
use strict;
use Getopt::Long;
use Pod::Usage;
use IO::CaptureOutput qw/capture/;
use Data::Dumper;
use GlobalConfig;
use ATest;
use Utils;

my $runtime_config;
my %opt;

sub parseOptArg{
  my $man = 0;
  my $help = 0;  
  GetOptions (
  'help|h' => \$help, man => \$man,
  "suite|s=s"  => \$opt{suite}
  );  
  pod2usage(1) if $help;
  pod2usage(-exitstatus => 0, -verbose => 2) if $man;
}

sub get_run_list{
  my $run_list;
  my $empty=1;
  if(exists($opt{suite}) && defined($opt{suite})){
    foreach my $suite(split(':',$opt{suite})){
      open(F,"$suite") || die $!;
      my @tc=();
      my @ts=();
      while(<F>){
	next if(/^\s*$/);     #skip blank line
	next if(/^\s*#.*$/);  #skip comments
	my $tc=$_;chomp($tc);
	push @tc, $tc;
	$empty=0;
      }
      close(F);
      push @ts,$suite;
      push @ts,\@tc;
      push @$run_list, \@ts;
    }
  }
#Add args
  my @tc=();my @ts=();
  foreach my $tc(@ARGV){
    utils_error "$tc does not exist!" if (! -e $tc);
    push @tc, "$tc";
    $empty=0;
  }
  push @ts,$config->{log_tag_unknown_suite}; 
  push @ts,\@tc;
  push @$run_list, \@ts;
#   my @list=@{$tc_list};
  utils_error "TC list empty,Nothing to run!" if ( $empty);
  return $run_list;
}

sub read_file{
  my ($file)=(@_);
  local $/=undef;
  open FILE, "$file" or die "Couldn't open file: $!";
  my $string = <FILE>;
  close FILE;
  return $string;
}

sub prepare{
  $runtime_config->{ts_timetag}=atest_timestamp;
  my ($log_folder,$this_run_log_folder)=($config->{log_folder},"$config->{log_folder}/$runtime_config->{ts_timetag}");
  $runtime_config->{this_run_log_folder}=$this_run_log_folder;
  `mkdir -p $log_folder` if(!-d $log_folder);
  `mkdir $this_run_log_folder` if(!-d $this_run_log_folder);
}

sub sys_log{
  my($txt,$log_file)=@_;
  utils_log("$config->{color_sys_log_prompt}$config->{log_tag_sys_log}|".
             atest_timestamp."$config->{color_reset}: $txt",$log_file);
}

sub append_total_log{
  

}

sub run{
  my ($ts_i,$tc_i,$ts,$tc_file)=(@_);
  my $code=read_file($tc_file);
  my ($stdout, $stderr)=("","");
  my $log_file=
  "$runtime_config->{this_run_log_folder}/${ts_i}_${tc_i}_TS__${ts}_TC__$tc_file.log";
  my $total_log_file="$runtime_config->{this_run_log_folder}/$config->{total_log}";
  
  my $chap="[$ts_i,$tc_i]";
  my $cmd="perl $tc_file $log_file $ts $chap";
  debug "$cmd";
  utils_info atest_timestamp." $chap $tc_file";
  my $sep=$config->{log_sep};
  my $mark=$config->{log_mark};
  my $start = time;
  eval {
    
    local $SIG{ ALRM } = sub { 
      my $kill_cmd="ps -ef |grep $runtime_config->{ts_timetag} | grep $tc_file | awk '\{print \$2\}' | xargs -i kill -15  {}";
      utils_run_cmd($kill_cmd);
      die "$tc_file TIMEOUT"; 
    };
    alarm $config->{tc_timeout};
    capture sub {
      utils_run_cmd($cmd);
    } => \$stdout, \$stderr;
    alarm 0;
  };

  if ( $@ =~ m/TIMEOUT/ ) {
#     utils_log("failed: operation timed out",$log_file);
#     utils_log($tc_file."|".atest_timestamp.": $tc_file $config->{log_tag_tc_status} timeout",$log_file);
#     sys_log("$tc_file $config->{log_tag_tc_status} timeout",$log_file);
    sys_log(sprintf("%s %s: %s %s",
            $tc_file,$config->{log_tag_tc_status},$chap,"$config->{color_log_fail}timeout$config->{color_reset}"),$log_file);
#     utils_alert("$tc_file timeout"."\n log file: ". $log_file."\"");
    utils_alert("$tc_file timeout");
  } elsif( $@) {
    warn "failed: $@\n";
  }
  my $end = time;
  my $execution_time=sprintf("%d sec\n", $end - $start);
  sys_log("$tc_file $config->{log_tag_exec_time} $execution_time",$log_file);
  utils_log("${mark}END_OF_TC_LOG${mark}",$log_file);
  utils_log("${mark}STDOUT${mark}\n$stdout\n${mark}EO_STDOUT${mark}\n${mark}STDERR${mark}\n$stderr\n${mark}EO_STDERR${mark}\n$sep\n",$log_file);
  
####append_toal_log
  utils_run_cmd("cat $log_file >>$total_log_file");
#   system("cat $log_file >>$total_log_file");
}


sub generate_rpt{
  my $generate_rpt_cmd="./generate_report.pl $runtime_config->{this_run_log_folder}";
  utils_run_cmd($generate_rpt_cmd);
  my $generate_log_html_cmd=
  "cat $runtime_config->{this_run_log_folder}/$config->{total_log} | aha >total_log.html";
  utils_run_cmd($generate_log_html_cmd);

}


sub main {
  parseOptArg;
  my $run_list=get_run_list;
#   print Data::Dumper->Dump([$run_list],["run_list"]);
#   exit;
  
  prepare;
  my $ts_i=1;
  foreach my $ts(@$run_list){
    my ($ts, $tc_ref)=($ts->[0],$ts->[1]);
    my $tc_i=1;
    foreach my $tc(@$tc_ref){
#         debug "$ts_i,$tc_i,$ts, $tc";
      run($ts_i,$tc_i,$ts, $tc);
      $tc_i++;
    }
    $ts_i++;
  }

  generate_rpt;

####tmp  
#   printn "cat $runtime_config->{this_run_log_folder}/* | grep TC_STATUS:";
#   printn "cat $runtime_config->{this_run_log_folder}/* | grep is_critical";
#   printn "cat $runtime_config->{this_run_log_folder}/* | grep EXEC";
#   printn "cat $runtime_config->{this_run_log_folder}/$config->{total_log} | aha >output.html && xdg-open output.html";
####tmp
}

main;


__END__
=head1 NAME

run.pl

=head1 SYNOPSIS

run.pl [options] <TC1 TC2 ...>

  Options:
    --help            brief help message
    --man             full documentation
    -s                run test suite
  Examples:
    ./run.pl -s aaron_test_suite
    ./run.pl -s aaron_test_suite:aaron_test_suite2
    ./run.pl tc1.pl tc2.pl tc3.pl
    ./run.pl -s aaron_test_suite tc1.pl tc2.pl

=head1 OPTIONS

=over 8

=item B<-h, --help>

Print a brief help message and exits.

=item B<-m, --man>

Prints the manual page and exits.

=item B<-s, --suite>

run test suites

=back

=head1 DESCRIPTION

run testcase

=cut
